#begin the part of parallel computing settings, while the above part is to initialize the iterable obj

.forparGlobals <- new.env(parent=emptyenv())

# this is called to register a parallel backend
setDoPar <- function(fun, data=NULL, info=function(data, item) NULL) {
  assign('fun', fun, pos=.forparGlobals, inherits=FALSE)
  assign('data', data, pos=.forparGlobals, inherits=FALSE)
  assign('info', info, pos=.forparGlobals, inherits=FALSE)
}

# this explicitly registers a sequential parallel backend
registerDoSEQ <- function() {
  setDoPar(doSEQ, NULL, info)
}

# passed to setDoPar via registerDoSEQ, and called by getDoParWorkers, etc
info <- function(data, item) {
  switch(item,
         workers=1L,
         name='doSEQ',
         version=packageDescription('forpar', fields='Version'),
         NULL)
}

# this returns a logical value indicating if a parallel backend
# has been registered or not
getDoParRegistered <- function() {
  exists('fun', where=.forparGlobals, inherits=FALSE)
}

# this returns the number of workers used by the currently registered
# parallel backend
getDoParWorkers <- function() {
  wc <- if (exists('info', where=.forparGlobals, inherits=FALSE))
    .foreachGlobals$info(.forparGlobals$data, 'workers')
  else
    NULL

  # interpret a NULL as a single worker, but the backend
  # can return NA without interference
  if (is.null(wc)) 1L else wc
}

# this returns the name of the currently registered parallel backend
getDoParName <- function() {
  if (exists('info', where=.forparGlobals, inherits=FALSE))
    .foreachGlobals$info(.forparGlobals$data, 'name')
  else
    NULL
}

# this returns the version of the currently registered parallel backend
getDoParVersion <- function() {
  if (exists('info', where=.forparGlobals, inherits=FALSE))
    .foreachGlobals$info(.forparGlobals$data, 'version')
  else
    NULL
}

# used internally to get the currently registered parallel backend
getDoPar <- function() {
  if (exists('fun', where=.forparGlobals, inherits=FALSE)) {
    list(fun=.forparGlobals$fun, data=.forparGlobals$data)
  } else {
    if (!exists('warningIssued', where=.forparGlobals, inherits=FALSE)) {
      warning('executing %dopar% sequentially: no parallel backend registered',
              call.=FALSE)
      assign('warningIssued', TRUE, pos=.forparGlobals, inherits=FALSE)
    }
    list(fun=doSEQ, data=NULL)
  }
}

setDoSMP <- function(w) {
   if (!inherits(w, "workergroup")) 
        stop("w must be a worker group object returned by startWorkers")
   if ("doSMP" %in% row.names(installed.packages())) {
   	  library(doSMP)
   	  registerDoSMP(w)
   } 
   assign('fun', doSEQ, pos=.forparGlobals, inherits=FALSE)
   list(fun=.forparGlobals$fun, data=.forparGlobals$data)
}

